<h1>NEURON + Java User reference</h1>
<h1>Java from the perspective of NEURON</h1>
This file discusses how to use java from NEURON's interpreter.
A user level discussion of
the converse is in
<a href="javanrn.html">"Writing java classes that communicate with NEURON".</a>

<p>
See also:<br>
<a href="doc/index.html">NEURON + Java Interface programmer reference</a>
<br> which is the javadoc generated information from the neuron.* classes
that implement the java to neuron interface.
<a href="njnotes.html">Early development notes</a> are
now mostly obsolete except for the important acknowlegement of
Fred Howell's original work on the interface.

<h2> Loading java classes into NEURON </h2>
<pre>
load_java("java.lang.String")
load_java("java.lang.String", "JString")
</pre>
This function registers a Java class with the Hoc interpreter. In hoc
the class is called <tt>java_lang_String</tt> or <tt>JString</tt>
respectively. The load_java function returns 1 if the class can be found and
registered, 2 if the name is already in use (hopefully because the
same class was previously loaded with that name),
and 0 (along with an
error message, probably ClassNotFoundException).
<p>
The same java classes may be loaded more than once with different
hoc names.
<p>
Java classes are looked for first in the current working directory, then
the list of directories or jar files specified in the ${CLASSPATH} environment
variable, then the jar files in the ${NEURONHOME}/classes directory, and finally
in the directories (or jar files) dynamically
added to the neuron/NrnClassLoader.
<p>
It should be noted that the
java virtual machine's system class loader starts with a java.class.path
variable which contains only the ${NEURONHOME}/classes/nrnclsld.jar
so that only the basic java classes and the neuron.NrnClassLoader are
loaded with the system loader. All other classes are loaded with the
neuron.NrnClassLoader which has a dynamically configurable list of
directories and jar files which are looked in for classes. This means that
if a class is loaded which fails due because it needs a package not in
the current classpath, that one can load that prerequisite package and
then attempt to reload the dependent class.
<p>
For example
<pre>
load_java("Notepad", "Notepad")
</pre>
returns 0 and prints the "java.lang.ClassNotFoundException: Notepad" message.
Re-executing with a third argument that specifies the path to the class gives
<pre>
load_java("Notepad", "Notepad", "file:/usr/j2sdk1_3_1/demo/jfc/Notepad/Notepad.jar")
</pre>
succeeds.
<h2> Java objects in NEURON</h2>
After a Java class is loaded, instances of the class (objects)
are created in the same way as native NEURON objects. e.g
<pre>
load_java("java.util.Vector", "JVector")
objref jv
jv = new JVector()
print jv // prints JVector[0]
</pre>
If there is more than one class constructor with args, better
performance is obtained using the no arg constructor (if it exists)
since that avoids a dynamic lookup of the proper constructor on the
basis of the specific hoc argument list used. Also, with overloaded
constructors, argument types double, int, and boolean cannot be distinguished
and all objects are of type object at the time the constructor selection
is made. In practice this is only rarely a problem. e.g.
<pre>
load_java("java.lang.String", "JString")
objref s
s = new String() // no problem
s = new String("Hello") // no problem
s = new String(s) // have to use s = new String(s.toCharArray)
/home/hines/nrn5/sparc/bin/nrniv: Expecting string argument near line 19
s = new String(s)        
                          ^
        String[2].init(String[1])
</pre>

<h2> Class Methods</h2>

The java class methods that can be called from hoc are
all of the public static methods and public instance
methods (along with all the inherited superclass methods)
that take arguments of java type:
<tt>
double
int
boolean
char[]
Object
</tt>
and return a value of any of these types or <tt>void</tt>.
<br>
Example
<pre>
load_java("java.lang.Math", "JMath")
objref jm
jm = new JMath()
jm.ceil(4.3) // prints 5
</pre>
If such methods are overloaded at the hoc level
then the correct method name in hoc is the method name followed by
the number of arguments followed by a signature string consisting
of the letters 'd', 'i', 'b', 's', or 'o' in the order of the arguments.
<br>
Example
<pre>
load_java("java.lang.Math", "JMath")
objref jm
jm = new JMath()
jm.min2ii(4.1, 3.1) // prints 3
jm.min2dd(4.1, 3.1) // prints 3.1
</pre>
Attempting to use the overloaded name will print a list of possible
disambiguated method names as in:
<pre>
oc>jm.min(4.1, 3.1)
JMath[0].min Overloaded. Use one of:
        min2ii
        min2dd
/home/hines/nrn5/sparc/bin/nrniv: min Overloaded.  Disambiguate using a
more specific method. near line 10
jm.min(4.1, 3.1)
                 ^
        JMath[0].min(4.1, 3.1)
oc>
</pre>
Notice that even pure static classes need an object instance in hoc
before one can call the static method.
<p>

<h2> What about unregistered Java objects? </h2>
If a java method returns an object that is unregistered (no load_java
call that registers that type), hoc encapsulates it as a JavaObject with
only two methods, "equals", and "name". JavaObject.equals(o) returns 1
only if the underlying native java object references are the same and
JavaObject.name() returns the class name of the underlying java object.
When (if) it goes back into java as an argument of another method
call, java receives it as its original type. Consider
<pre>
load_java("java.util.Vector", "JVector")
objref jv, o
jv = new JVector()
o = jv.toString // but the java String is unregistered
oc>print o
JavaObject[0] 
oc> o.name // prints the underlying classname of the java object
        class java.lang.String 
jv.add1o(o) // now put that object into jv
print jv.get(0) // still a JavaObject but not the same hoc version of it.
jv.get(0).equals(o) // but they really are the same
load_java("java.lang.String", "JString")
print jv.get(0).toCharArray // Now it comes back as the proper JString!
</pre>

<h2> What about passing Hoc objects that Java knows nothing about? </h2>
In this case java encapsulates it as an opaque HocObject. When it is
returned by a method, it is unpacked and reappears as the original
hoc object. E.g.
<pre>
load_java("java.util.Vector", "JVector")
objref jv
jv = new JVector()
jv.add1o(new Graph())
print jv.get(0) //prints Graph[0] (if it was the first vector created)
jv.get(0).size(-100,100,-200,200)
</pre>

<h2> Watch out! Different hoc objects can reference the same java object! </h2>

For normal native hoc objects, different internal names of the object
(template name followed by an index in brackets) imply distinct object
instances. But a java object in hoc is really a reference back to the
java object in Java. Thus different internal hoc object
names can actually refer to the same java object.
Consider
<pre>
load_java("java.util.Vector", "JV")
objref jv1, jv2
jv1 = new JV()
jv1.add1o(new Vector())
jv1.add1o(jv1)
jv2 = jv1.get(1)
jv1 // prints JV[0]
jv2 // prints JV[1]
jv1 == jv2 /// they are different hoc objects
jv1.equals(jv2) // but they are the same java object
</pre>

If this causes too much trouble in the future, then the
jv1 == jv2 semantics can be changed.
